package com.example.service.medical;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.common.Constants;
import com.example.common.enums.ResultCodeEnum;
import com.example.common.enums.RoleEnum;
import com.example.common.enums.RoleStatusEnum;
import com.example.exception.CustomException;
import com.example.mapper.appointment.PlanMapper;
import com.example.mapper.appointment.ReservationMapper;
import com.example.mapper.medical.DoctorMapper;


import com.example.mapper.medical.HospitalMapper;
import com.example.mapper.medical.OfficeMapper;
import com.example.model.dto.AccountDto;
import com.example.model.dto.DoctorDto;
import com.example.model.dto.HospitalDto;
import com.example.model.entity.appointment.Plan;
import com.example.model.entity.appointment.Reservation;
import com.example.model.entity.medical.Doctor;
import com.example.model.entity.medical.Hospital;
import com.example.model.entity.medical.Office;
import com.example.model.entity.other.Account;
import com.example.model.entity.tribune.Post;
import com.example.model.vo.DoctorVo;
import com.example.utils.TokenUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import javax.annotation.Resource;

import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 医生表业务处理
 **/
@Service
public class DoctorService {


    @Resource
    private DoctorMapper doctorMapper;
    @Resource
    private OfficeMapper officeMapper;
    @Resource
    private ReservationMapper reservationMapper;
    @Resource
    private HospitalMapper hospitalMapper;
    @Resource
    private PlanMapper planMapper;

    /**
     * 新增
     */
    public void add(Doctor doctor) {
        Doctor dbDoctor = doctorMapper.selectByUsername(doctor.getUsername());
        if (ObjectUtil.isNotNull(dbDoctor)) {
            throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR);
        }
        Account currentUser = TokenUtils.getCurrentUser();
        if(RoleEnum.HOSPITAL.name().equals(currentUser.getRole())){
            doctor.setHospitalId(currentUser.getId());
        }
        if (ObjectUtil.isEmpty(doctor.getPassword())) {
            doctor.setPassword(Constants.DOCTOR_DEFAULT_PASSWORD);
        }
        doctor.setCount(0);
        doctor.setRole(RoleEnum.DOCTOR.name());
        doctor.setStatus(RoleStatusEnum.STATUS_OK.getName());
        doctorMapper.insert(doctor);
    }

    /**
     * 删除
     */
    public void deleteById(Integer id) {
        doctorMapper.deleteById(id);
    }

    /**
     * 批量删除
     */
    public void deleteBatch(List<Integer> ids) {
        for (Integer id : ids) {
            doctorMapper.deleteById(id);
        }
    }

    /**
     * 修改
     */
    public void updateById(Doctor doctor) {
        doctorMapper.updateById(doctor);
    }



    /**
     * 根据ID查询
     */
    public Doctor selectById(Integer id) {
        return doctorMapper.selectById(id);
    }

    public DoctorVo selectDetailById(Integer id) {
        Doctor doctor = doctorMapper.selectById(id);
        // 生成token
        String tokenData = doctor.getId() + "-" + RoleEnum.DOCTOR.name();
        String token = TokenUtils.createToken(tokenData, doctor.getPassword());
        doctor.setToken(token);
        DoctorVo doctorVo= new DoctorVo();
        BeanUtils.copyProperties(doctor,doctorVo);
        Office office = officeMapper.selectById(doctor.getOfficeId());
        String officeName = office.getOfficeName();
        doctorVo.setOfficeName(officeName);
        return doctorVo;
    }

    /**
     * 查询所有
     */
    public List<Doctor> selectAll(Doctor doctor) {
        Account currentUser = TokenUtils.getCurrentUser();
        if(RoleEnum.HOSPITAL.name().equals(currentUser.getRole())){
            doctor.setHospitalId(currentUser.getId());
        }
        return doctorMapper.selectAll(doctor);
    }

    /**
     * 分页查询
     */
    public PageInfo<Doctor> selectPage(Doctor doctor, Integer pageNum, Integer pageSize) {
        Account currentUser = TokenUtils.getCurrentUser();
        if(RoleEnum.HOSPITAL.name().equals(currentUser.getRole())){
            doctor.setHospitalId(currentUser.getId());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Doctor> list = doctorMapper.selectAll(doctor);
        return PageInfo.of(list);
    }
    public PageInfo<DoctorVo> selectFrontPage(Doctor doctor, Integer pageNum, Integer pageSize) {
        // 查询所有符合条件的医生数据
        List<DoctorVo> allDoctors = doctorMapper.selectFrontAll(doctor);

        // 过滤不符合条件的医生
        Iterator<DoctorVo> iterator = allDoctors.iterator();
        while (iterator.hasNext()) {
            DoctorVo doctorVo = iterator.next();
            List<Plan> planList = planMapper.selectByDoctorId(doctorVo.getId());
            doctorVo.setPlanList(planList);
            if (doctor.getWeek() != null || doctor.getTime() != null) {
                boolean hasValidPlan = false;
                for (Plan plan : planList) {
                    String week = plan.getWeek();
                    String time = plan.getTime().substring(0, 2);
                    if (doctor.getWeek() != null && doctor.getTime() == null) {
                        if (doctor.getWeek().equals(week)) {
                            hasValidPlan = true;
                            break;
                        }
                    } else if (doctor.getWeek() == null) {
                        if (doctor.getTime().substring(0, 2).equals(time)) {
                            hasValidPlan = true;
                            break;
                        }
                    } else {
                        if (doctor.getWeek().equals(week) && doctor.getTime().substring(0, 2).equals(time)) {
                            hasValidPlan = true;
                            break;
                        }
                    }
                }
                if (!hasValidPlan) {
                    iterator.remove();
                }
            }
        }
        // 使用 PageHelper 对过滤后的数据进行分页
        PageHelper.startPage(pageNum, pageSize);
        List<DoctorVo> pagedDoctors = allDoctors.stream()
                .skip((long) (pageNum - 1) * pageSize)
                .limit(pageSize)
                .collect(Collectors.toList());

        // 创建 PageInfo 对象
        PageInfo<DoctorVo> pageInfo = new PageInfo<>(pagedDoctors);
        pageInfo.setTotal(allDoctors.size());
        return pageInfo;
    }




    public void updateBatch(DoctorDto doctorDto) {
        for (Integer id :doctorDto.getIds()) {
            String status = doctorDto.getStatus();
            Doctor doctor =doctorMapper.selectById(id);
            doctor.setStatus(status);
            doctorMapper.updateById(doctor);
        }
    }

    /**
     * 登录
     */
    public Account login(AccountDto accountDto) {
        Account dbDoctor = doctorMapper.selectByUsername(accountDto.getUsername());
        if (ObjectUtil.isNull(dbDoctor)) {
            throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
        }
        if (!accountDto.getPassword().equals(dbDoctor.getPassword())) {
            throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR);
        }
        // 生成token
        String tokenData = dbDoctor.getId() + "-" + RoleEnum.DOCTOR.name();
        String token = TokenUtils.createToken(tokenData, dbDoctor.getPassword());
        dbDoctor.setToken(token);
        return dbDoctor;
    }

    /**
     * 修改密码
     */
    public void updatePassword(Account account) {
        Doctor dbDoctor = doctorMapper.selectByUsername(account.getUsername());
        if (ObjectUtil.isNull(dbDoctor)) {
            throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
        }
        if (!account.getPassword().equals(dbDoctor.getPassword())) {
            throw new CustomException(ResultCodeEnum.PARAM_PASSWORD_ERROR);
        }
        dbDoctor.setPassword(account.getNewPassword());
        doctorMapper.updateById(dbDoctor);
    }


    public List<Dict> selectLine() {
        Account currentUser = TokenUtils.getCurrentUser();
        List<Dict> dictList = new ArrayList<>();
        // 1. 获取当前日期和一周前的日期
        Date date = new Date();
        DateTime start = DateUtil.offsetDay(date, -7);
        DateTime end = DateUtil.offsetDay(date, -1);
        // 2. 获取指定医生在这段时间内的所有预约记录
        List<Reservation> reservationsList = reservationMapper.selectByDoctorAndDateRange(currentUser.getId(), start, end);
        // 3. 将预约记录按日期分组
        List<DateTime> dateTimes = DateUtil.rangeToList(start, end, DateField.DAY_OF_YEAR);
        List<String> dateList = dateTimes.stream().map(DateUtil::formatDate).sorted(Comparator.naturalOrder()).collect(Collectors.toList());
        // 4. 统计每一天的预约数量
        for (String day : dateList) {
            long count = reservationsList.stream().filter(reservation -> DateUtil.formatDate(reservation.getAppointmentDate()).equals(day)).count();
            Dict dict = Dict.create().set("name", day).set("value", count);
            dictList.add(dict);
        }

        return dictList;
    }


    /**
     * 查询挂号量靠前10的医生
     * @return
     */
    public List<Doctor> selectTopDoctor() {
        return doctorMapper.selectTopDoctor();
    }

    /**
     * 根据信息查询医生
     * @param doctorDto 医生信息
     * @return
     */
    public PageInfo<Doctor> selectByInfo(DoctorDto doctorDto) {
        PageHelper.startPage(doctorDto.getPageNum(),doctorDto.getPageSize());
        List<Doctor> doctorList = doctorMapper.selectByInfo(doctorDto.getHospitalId());
        // 设置医院名称
        doctorList.forEach(doctor -> {
            Hospital hospital = hospitalMapper.selectById(doctor.getHospitalId());
            doctor.setHospitalName(hospital.getName());
        });
        return PageInfo.of(doctorList);
    }


    public PageInfo<DoctorVo> getDoctorInfoByHospitalId(Long hospitalId, Integer pageNum, Integer pageSize) {
        if (hospitalId == null || hospitalId <= 0) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        Hospital hospital = hospitalMapper.selectById(hospitalId.intValue());
        if (hospital == null) {
            throw new CustomException(ResultCodeEnum.HOSPITAL_NOT_EXIST_ERROR);
        }
        String hospitalName = hospital.getName();
        // 在查询医生列表之前调用PageHelper.startPage()进行分页
        PageHelper.startPage(pageNum, pageSize);
        List<Doctor> doctorList = doctorMapper.selectByHospitalId(hospitalId.intValue());

        List<DoctorVo> doctorVoList = new ArrayList<>();
        for (Doctor doctor : doctorList) {
            DoctorVo doctorVo = new DoctorVo();
            BeanUtils.copyProperties(doctor, doctorVo);
            List<Plan> planList = planMapper.selectByDoctorId(doctor.getId());
            Integer officeId = doctor.getOfficeId();
            Office office = officeMapper.selectById(officeId);
            String officeName = office.getOfficeName();
            doctorVo.setPlanList(planList);
            doctorVo.setHospitalName(hospitalName);
            doctorVo.setOfficeName(officeName);
            doctorVoList.add(doctorVo);
        }
        // 使用PageInfo包装查询结果，这样便可以获取分页信息
        return new PageInfo<>(doctorVoList);
    }

    /**
     * 根据科室ID查询医生详细信息
     * @param officeId 科室 id
     */
    public PageInfo<DoctorVo> getDoctorInfoByOfficeId(Long officeId, Integer pageNum, Integer pageSize) {
        if (officeId == null || officeId <= 0) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Doctor> doctorList = doctorMapper.selectByOfficeId(officeId.intValue());
        List<DoctorVo> doctorVoList = new ArrayList<>();
        for (Doctor doctor : doctorList) {
            DoctorVo doctorVo = new DoctorVo();
            BeanUtils.copyProperties(doctor, doctorVo);
            Hospital hospital = hospitalMapper.selectById(doctor.getHospitalId());
            String hospitalName = hospital.getName();
            Office office = officeMapper.selectById(doctor.getOfficeId());
            String officeName = office.getOfficeName();
            List<Plan> planList = planMapper.selectByDoctorId(doctor.getId());
            doctorVo.setPlanList(planList);
            doctorVo.setHospitalName(hospitalName);
            doctorVo.setOfficeName(officeName);
            doctorVoList.add(doctorVo);
        }
        // 使用PageInfo包装查询结果，这样便可以获取分页信息
        return PageInfo.of(doctorVoList);
    }

    /**
     * 查询同科室医生信息
     * @param doctorId 医生 id
     */
    public List<Doctor> selectSameOfficeDoctorByDoctorId(Long doctorId) {
        if (doctorId == null || doctorId <= 0) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        Doctor doctor = doctorMapper.selectById(doctorId.intValue());
        if (doctor == null) {
            return new ArrayList<>();
        }
        Integer officeId = doctor.getOfficeId();
        return doctorMapper.selectByOfficeId(officeId);
    }
    /**
     * 根据医生ID查询医生详细信息
     * @param doctorId 医生 id
     */
    public DoctorVo getDoctorInfoByDoctorId(Long doctorId) {
        if (doctorId == null || doctorId <= 0) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        DoctorVo doctorVo = new DoctorVo();
        Doctor doctor = doctorMapper.selectById(doctorId.intValue());
        if (doctor == null) {
            return new DoctorVo();
        }
        Hospital hospital = hospitalMapper.selectById(doctor.getHospitalId());
        String hospitalName = hospital.getName();
        Office office = officeMapper.selectById(doctor.getOfficeId());
        String officeName = office.getOfficeName();
        String officePhone = office.getPhone();
        List<Plan> planList = planMapper.selectByDoctorId(doctor.getId());
        BeanUtils.copyProperties(doctor, doctorVo);
        doctorVo.setPlanList(planList);
        doctorVo.setHospitalName(hospitalName);
        doctorVo.setOfficeName(officeName);
        doctorVo.setOfficePhone(officePhone);
        return doctorVo;
    }


}
